package edu.se.jai.gameservice.service;

import com.sun.org.apache.bcel.internal.generic.RETURN;
import edu.se.jai.dubboapi.proto.GameServiceProto;
import edu.se.jai.dubboapi.proto.GameServiceProto.*;
import edu.se.jai.dubboapi.service.GameServiceApi;
import edu.se.jai.gameservice.dto.Result;  // Java DTO
import edu.se.jai.gameservice.dto.GuessResultDto;  // Java DTO
import edu.se.jai.gameservice.entity.GameRoom;
import edu.se.jai.gameservice.entity.Player;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 游戏服务 Dubbo 实现类
 * 
 * 🎯 架构设计：
 * - 实现 GameServiceApi 接口，暴露 Dubbo RPC 服务
 * - 调用 GameService 业务逻辑层，复用原有业务逻辑
 * - 负责将 Java DTO 转换为 Protobuf 格式
 * - 使用 Triple 协议和 Protobuf 序列化
 * 
 * 📦 分层架构：
 * - GameServiceImpl (Dubbo层) -> GameService (业务逻辑层) -> Redis (数据层)
 * - GameServiceImpl 只负责协议转换，不包含业务逻辑
 * - GameService 保持原有逻辑不变，便于维护和测试
 * 
 * 📝 注解说明：
 * - @DubboService：暴露Dubbo服务，同时自动注册为Spring Bean（无需@Service）
 * - interfaceClass：指定服务接口
 * - protocol = "tri"：使用Triple协议（Dubbo 3.x推荐）
 */
@Slf4j
@DubboService(interfaceClass = GameServiceApi.class, protocol = "tri")
@RequiredArgsConstructor
public class GameServiceImpl implements GameServiceApi {

    private final GameService gameService;

    @Override
    public GameServiceProto.Result registerPlayer(RegisterPlayerRequest request) {
        String sessionId = request.getSessionId();
        String playerName = request.getPlayerName();
        log.debug("Dubbo调用 - 注册玩家: sessionId={}, playerName={}", sessionId, playerName);

        // 调用业务逻辑层
        Result<String> serviceResult = gameService.registerPlayerSession(sessionId, playerName);
        
        // 转换为Protobuf格式
        if (serviceResult.isSuccess()) {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(true)
                    .setStringData(serviceResult.getData())
                    .build();
        } else {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage(serviceResult.getErrorMessage())
                    .build();
        }
    }

    @Override
    public GameServiceProto.Result clearPlayer(SessionRequest request) {
        String sessionId = request.getSessionId();
        log.debug("Dubbo调用 - 清除玩家: sessionId={}", sessionId);

        // 调用业务逻辑层
        Result<String> serviceResult = gameService.clearPlayerSession(sessionId);
        
        // 转换为Protobuf格式
        if (serviceResult.isSuccess()) {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(true)
                    .setStringData(serviceResult.getData())
                    .build();
        } else {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage(serviceResult.getErrorMessage())
                    .build();
        }
    }

    @Override
    public GameServiceProto.Result createRoom(SessionRequest request) {
        String sessionId = request.getSessionId();
        log.debug("Dubbo调用 - 创建房间: sessionId={}", sessionId);

        // 调用业务逻辑层
        Result<GameRoom> serviceResult = gameService.createRoom(sessionId);
        
        // 转换为Protobuf格式
        if (serviceResult.isSuccess()) {
            GameRoomDto protoDto = convertToProtoGameRoomDto(serviceResult.getData());
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(true)
                    .setGameRoomDto(protoDto)
                    .build();
        } else {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage(serviceResult.getErrorMessage())
                    .build();
        }
    }

    @Override
    public GameServiceProto.Result joinRoom(SessionRoomRequest request) {
        String sessionId = request.getSessionId();
        String roomId = request.getRoomId();
        log.debug("Dubbo调用 - 加入房间: sessionId={}, roomId={}", sessionId, roomId);

        // 调用业务逻辑层
        Result<GameRoom> serviceResult = gameService.joinRoom(sessionId, roomId);
        
        // 转换为Protobuf格式
        if (serviceResult.isSuccess()) {
            GameRoomDto protoDto = convertToProtoGameRoomDto(serviceResult.getData());
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(true)
                    .setGameRoomDto(protoDto)
                    .build();
        } else {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage(serviceResult.getErrorMessage())
                    .build();
        }
    }

    @Override
    public GameServiceProto.Result leaveRoom(SessionRoomRequest request) {
        String sessionId = request.getSessionId();
        String roomId = request.getRoomId();
        log.debug("Dubbo调用 - 离开房间: sessionId={}, roomId={}", sessionId, roomId);

        // 调用业务逻辑层
        Result<GameRoom> serviceResult = gameService.leaveRoom(sessionId, roomId);
        
        // 转换为Protobuf格式
        if (serviceResult.isSuccess()) {
            GameRoomDto protoDto = convertToProtoGameRoomDto(serviceResult.getData());
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(true)
                    .setGameRoomDto(protoDto)
                    .build();
        } else {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage(serviceResult.getErrorMessage())
                    .build();
        }
    }

    @Override
    public GameServiceProto.Result dissolveRoom(SessionRoomRequest request) {
        String sessionId = request.getSessionId();
        String roomId = request.getRoomId();
        log.debug("Dubbo调用 - 解散房间: sessionId={}, roomId={}", sessionId, roomId);

        // 调用业务逻辑层
        Result<GameRoom> serviceResult = gameService.dissolveRoom(sessionId, roomId);
        
        // 转换为Protobuf格式
        if (serviceResult.isSuccess()) {
            GameRoomDto protoDto = convertToProtoGameRoomDto(serviceResult.getData());
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(true)
                    .setGameRoomDto(protoDto)
                    .build();
        } else {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage(serviceResult.getErrorMessage())
                    .build();
        }
    }

    @Override
    public GameServiceProto.Result getAllRooms(AllRoomsRequest request) {
        String sessionId = request.getSessionId();
        log.debug("Dubbo调用 - 获取所有房间: sessionId={}", sessionId);
        
        // 调用业务逻辑层
        List<GameRoom> rooms = gameService.getAllRooms();
        
        // 转换为Protobuf格式
        GameRoomList.Builder listBuilder = GameRoomList.newBuilder();
        rooms.forEach(room -> {
            GameRoomDto protoDto = convertToProtoGameRoomDto(room);
            listBuilder.addRooms(protoDto);
        });
        
        return GameServiceProto.Result.newBuilder()
                .setSuccess(true)
                .setGameRoomList(listBuilder.build())
                .build();
    }

    @Override
    public GameServiceProto.Result getRoomBySessionId(SessionRequest request) {
        String sessionId = request.getSessionId();
        log.debug("Dubbo调用 - 根据会话ID获取房间: sessionId={}", sessionId);

        // 调用业务逻辑层
        GameRoom room = gameService.getRoomBySessionId(sessionId);
        
        // 转换为Protobuf格式
        if (room == null) {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage("房间不存在")
                    .build();
        }
        
        GameRoomDto protoDto = convertToProtoGameRoomDto(room);
        return GameServiceProto.Result.newBuilder()
                .setSuccess(true)
                .setGameRoomDto(protoDto)
                .build();
    }

    @Override
    public GameServiceProto.Result getRoomById(RoomIdRequest request) {
        String roomId = request.getRoomId();
        log.debug("Dubbo调用 - 根据房间ID获取房间: roomId={}", roomId);

        // 调用业务逻辑层
        GameRoom room = gameService.getRoomById(roomId);
        
        // 转换为Protobuf格式
        if (room == null) {
            return GameServiceProto.Result.newBuilder()
                    .setSuccess(false)
                    .setErrorMessage("房间不存在")
                    .build();
        }
        
        GameRoomDto protoDto = convertToProtoGameRoomDto(room);
        return GameServiceProto.Result.newBuilder()
                .setSuccess(true)
                .setGameRoomDto(protoDto)
                .build();
    }

    @Override
    public GameServiceProto.Result startGame(SessionRoomRequest request) {
        String sessionId = request.getSessionId();
        String roomId = request.getRoomId();
        log.debug("Dubbo调用 - 开始游戏: sessionId={}, roomId={}", sessionId, roomId);

        Result<GameRoom> serviceResult = null;
        // todo 练习三 3. 调用gameService的 startGame,结果赋值到serviceResult


        if (serviceResult.isSuccess()) {
            GameRoomDto protoDto = convertToProtoGameRoomDto(serviceResult.getData());
            // todo 练习三  4. 成功 返回  GameServiceProto.Result

        } else {
            // todo 练习三  5. 失败 返回  GameServiceProto.Result

        }
        return  null;//完成练习后删除
    }

    @Override
    public GameServiceProto.Result stopGame(SessionRoomRequest request) {
        String sessionId = request.getSessionId();
        String roomId = request.getRoomId();
        log.debug("Dubbo调用 - 停止游戏: sessionId={}, roomId={}", sessionId, roomId);

        Result<GameRoom> serviceResult = null;
        // todo  练习三 3. 调用gameService的 stopGame,结果赋值到serviceResult


        if (serviceResult.isSuccess()) {
            GameRoomDto protoDto = convertToProtoGameRoomDto(serviceResult.getData());
            // todo  练习三 4. 成功 返回  GameServiceProto.Result

        } else {
            // todo  练习三 5. 失败 返回  GameServiceProto.Result

        }
        return  null;//完成练习后删除

    }

    @Override
    public GameServiceProto.Result makeGuess(GuessDto request) {
        log.debug("Dubbo调用 - 猜测数字: sessionId={}, roomId={}, guess={}", 
                request.getSessionId(), request.getRoomId(), request.getGuess());
        
       // todo 练习四 3. 根据 request内的信息调用gameService.makeGuess


        // todo 练习四 4. 构造 GameServiceProto.GuessResultDto，以及 GameServiceProto.Result并返回，可能成功，可能失败

        return null;//完成练习后删除
    }

    // ==================== 私有辅助方法：转换 Java DTO -> Protobuf ====================
    
    /**
     * 将内部GameRoom实体转换为Protobuf GameRoomDto
     * 
     * 注意：不包含 targetNumber 敏感信息
     */
    private GameRoomDto convertToProtoGameRoomDto(GameRoom room) {
        if (room == null) {
            return null;
        }
        
        // 转换GameStatus枚举：Java -> Protobuf
        GameServiceProto.GameStatus protoStatus;
        if (room.getStatus() == edu.se.jai.gameservice.dto.GameStatus.WAITING) {
            protoStatus = GameServiceProto.GameStatus.WAITING;
        } else {
            protoStatus = GameServiceProto.GameStatus.PLAYING;
        }
        
        // 构建Protobuf对象
        GameRoomDto.Builder builder = GameRoomDto.newBuilder();
        builder.setRoomId(room.getRoomId());
        builder.setCreatorName(room.getCreatorName());
        builder.setStatus(protoStatus);
        
        if (room.getPlayers() != null) {
            List<String> nameList = room.getPlayers().values().stream()
                    .map(Player::getName)
                    .collect(Collectors.toList());
            builder.addAllPlayers(nameList);
        }
        
        return builder.build();
    }
}
